﻿/*
	This file is part of Limpet.

    Limpet is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Limpet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Limpet.  If not, see http://www.gnu.org/licenses/.
	
	Copyright 2010 Dan Popick
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web.UI;

namespace Open.Web.Diagnostics.Limpet
{
    /// <summary>
    /// A user control which renders the Limpet data into a web page
    /// </summary>
    public class LimpetNode: UserControl
    {
        // taken from Rick Strahl: https://www.west-wind.com/Weblog/posts/114530.aspx
        static string EncodeJsString(string s)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("\"");
            foreach (char c in s)
            {
                switch (c)
                {
                    case '\"':
                        sb.Append("\\\"");
                        break;
                    case '\\':
                        sb.Append("\\\\");
                        break;
                    case '\b':
                        sb.Append("\\b");
                        break;
                    case '\f':
                        sb.Append("\\f");
                        break;
                    case '\n':
                        sb.Append("\\n");
                        break;
                    case '\r':
                        sb.Append("\\r");
                        break;
                    case '\t':
                        sb.Append("\\t");
                        break;
                    default:
                        int i = (int)c;
                        if (i < 32 || i > 127)
                            sb.AppendFormat("\\u{0:X04}", i);
                        else
                            sb.Append(c);
                        break;
                }
            }
            sb.Append("\"");

            return sb.ToString();
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            if (Request.Cookies[LimpetManager.Config.CookieName] == null)
                return;

            if (LimpetManager.Config.AllowedAddresses.Count > 0)
            {
                IPAddress addr;
                if (!IPAddress.TryParse(Request.UserHostAddress, out addr))
                    return;

                if (!IPUtil.FindSubnetMatch(addr, LimpetManager.Config.AllowedAddresses))
                    return;
            }

            // the div needs a specific id
            writer.AddAttribute(HtmlTextWriterAttribute.Id, "_limpet_div");
            // mark the div as "display: none" to hide it.
            writer.AddAttribute(HtmlTextWriterAttribute.Style, "display: none;");
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            // Add a filter which converts the JSON data to base64-encoded, AES-encrypted data
            // it's a little stupid since we can only write full unicode to the HTML text writer
            // so we use this intermediate stream to contain the raw ASCII-encoded result
            MemoryStream ms = new MemoryStream();
            Base64EncodingStream base64stream = new Base64EncodingStream(ms);
            PageFilterEncryptionStream encString = new PageFilterEncryptionStream(base64stream);
            StreamWriter sw = new StreamWriter(encString);

            bool writeComma = false;

            sw.Write("[");
            foreach (SummaryMessage message in LimpetManager.GetMessages())
            {
                if (message == null)
                    continue;

                if (writeComma)
                    sw.Write(',');
                else
                    writeComma = true;

                sw.Write("{");
                sw.Write("\"severity\": \"{0}\",", message.Severity);
                sw.Write("\"category\": {0},", EncodeJsString(message.Category));
                sw.Write("\"text\": {0},", EncodeJsString(message.Text));
                sw.Write("\"dataUrl\": {0}", EncodeJsString(message.Url));
                sw.Write("}");
            }
            sw.Write("]");

            sw.Flush();

            writer.Write(Encoding.ASCII.GetString(ms.ToArray()));

            writer.RenderEndTag();
        }

    }
}
